﻿Imports System.Threading
Public Class CReadWriteLock

    '' スレッドロック用
    Private Shared m_event As System.Threading.AutoResetEvent
    Private Shared m_event1 As System.Threading.AutoResetEvent

    Private m_readFlg As Boolean = False
    Private m_writeFlg As Boolean = False

    Dim m_LockObject As New Object
    Dim m_UnLockObject As New Object

    Dim T_Manager As ThreadManager


    Public Sub New()
        m_event = New System.Threading.AutoResetEvent(False)
        m_event1 = New System.Threading.AutoResetEvent(False)
        T_Manager = ThreadManager.getInstance

    End Sub

    'ロック
    Public Function ReadLock(ByVal m_time As Integer) As Boolean

        'ReadLockスレッド数を記憶する
        'T_Manager.setReadLock()

        'Monitor.Enter(m_LockObject)
        Monitor.Enter(T_Manager)
        T_Manager.setReadLock()
        Monitor.Enter(m_UnLockObject)

        'WriteLockスレッドを判別
        If T_Manager.getWriteLock > 0 Then
            Monitor.Exit(m_UnLockObject)
            'WriteLockが解除するまで
            ''Debug.WriteLine("Write部分")
            'Debug.WriteLine("WriteLockがかかって待ってる")
            m_event.WaitOne()
            Monitor.Enter(m_UnLockObject)

            'WriteLockがスレッドに残ったら
            Do
                If T_Manager.getWriteLock = 0 Then Exit Do
                Monitor.Exit(m_UnLockObject)
                ''Debug.WriteLine("Read Do部分")
                'Debug.WriteLine("WriteLockがかかって待ってる")
                m_event.WaitOne()
                Monitor.Enter(m_UnLockObject)
            Loop
            ''Debug.WriteLine("WriteLock解除")
            'Debug.WriteLine("ReadLock開始")
        ElseIf T_Manager.getReadLock > 0 Then
            'Debug.WriteLine("ReadLock開始")
        End If

        Monitor.Exit(m_UnLockObject)
        'Monitor.Exit(m_LockObject)
        Monitor.Exit(T_Manager)


    End Function

    'ロック
    Public Sub WriteLock(ByVal m_time As Integer)

        'WriteLockスレッド数を記憶する
        'T_Manager.setWriteLock()

        'Monitor.Enter(m_LockObject)
        Monitor.Enter(T_Manager)
        T_Manager.setWriteLock()
        Monitor.Enter(m_UnLockObject)

        'ReadLockがある場合
        If T_Manager.getReadLock > 0 Then
            Monitor.Exit(m_UnLockObject)
            'ReadLockが解除するまで
            'Debug.WriteLine("ReadLockがかかって待ってる")
            m_event1.WaitOne()
            Monitor.Enter(m_UnLockObject)

            Do
                If T_Manager.getReadLock = 0 Then Exit Do
                Monitor.Exit(m_UnLockObject)
                'Debug.WriteLine("Write Do部分")
                'Debug.WriteLine("ReadLockがかかって待ってる")
                m_event1.WaitOne()
                Monitor.Enter(m_UnLockObject)
            Loop

            'Debug.WriteLine("ReadLock解除")

            'Do
            '    If T_Manager.getWriteLock = 0 Then Exit Do
            '    Monitor.Exit(m_UnLockObject)
            '    'Debug.WriteLine("Write部分")
            '    'Debug.WriteLine("WriteLockがかかって待ってる")
            '    m_event.WaitOne()
            '    Monitor.Enter(m_UnLockObject)
            'Loop

            'If T_Manager.getWriteLock = 0 Then
            '    'Debug.WriteLine("WriteLock解除")
            'End If

            '自分のWriteLock以外WriteLockがあれば
        ElseIf T_Manager.getWriteLock > 1 Then
            Monitor.Exit(m_UnLockObject)
            'WriteLockが解除するまで
            'Debug.WriteLine("WriteLockがかかって待ってる")
            m_event.WaitOne()
            Monitor.Enter(m_UnLockObject)

            '
            'Do
            '    If T_Manager.getWriteLock = 0 Then Exit Do
            '    Monitor.Exit(m_UnLockObject)
            '    'WriteLockが解除するまで
            '    'Debug.WriteLine("Write部分した")
            '    'Debug.WriteLine("WriteLockがかかって待ってる")
            '    m_event.WaitOne()
            '    Monitor.Enter(m_UnLockObject)
            'Loop

            ''Debug.WriteLine("WriteLockの解除")

        End If

        'Debug.WriteLine("WriteLockの開始")
        Monitor.Exit(m_UnLockObject)
        'Monitor.Exit(m_LockObject)
        Monitor.Exit(T_Manager)


    End Sub

    'ロック解除
    Public Sub ReleaseReadLock()

        Monitor.Enter(m_UnLockObject)
        'Debug.WriteLine("ReadLock解除")
        T_Manager.delReadLock()
        Monitor.Exit(m_UnLockObject)
        m_event1.Set()

    End Sub

    'ロック解除
    Public Sub ReleaseWriteLock()

        Monitor.Enter(m_UnLockObject)
        'Debug.WriteLine("WriteLock解除")
        T_Manager.delWriteLock()
        Monitor.Exit(m_UnLockObject)
        m_event.Set()
    End Sub



End Class

